package com.sunbeam.common.utils.encrypt;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;

import com.sunbeam.common.consts.EConstants;
import com.sunbeam.common.utils.StringUtils;

/**
 * @Title: MD5Utils.java
 * @Package com.sunbeam.common.utils
 * @Description: TODO
 * @author lyz lyzpoq_gmail_com
 * @date 2013/09/03 9:32:16
 * @version V1.0
 */
public class EncryptUtils extends StringUtils {

	/**
	 * @Title: main
	 * @Description: TODO
	 * @param @param args
	 * @return void
	 * @throws
	 */
	static char[] hexLowCase = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f' };
	static char[] hexUpCase = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','A', 'B', 'C', 'D', 'E', 'F' };
    public static String key=EConstants.INIT_ENCRYPTION_KEY;
    
    //************************TestMain**************************************
	public static void main(String[] args) {
        //key="0";

//		Long l1=System.currentTimeMillis();
		//while(Integer.parseInt(key)<1000){
//			String encryptedStr=encrypt2StringByDES(key);
//			System.out.println(encryptedStr);
//			System.out.println(decrypt2StringByDES(encryptedStr));
//			key=(Integer.parseInt(key)+1)+"";
//			for(byte b:encrypt2BytesByDES(key)){
//				System.out.print(b+" ");
//			}
//			System.out.println("\r\nencryptedStr.length="+encryptedStr.length());
		//}
//		Long l2=System.currentTimeMillis();
//		System.out.println((l2-l1)/1000.0+"ms");	
//		System.out.println(encrypt2StringOnLog("z").length()+":\t"+encrypt2StringOnLog("abcdefghijklmnopqrstuvwxyz"));
//		for(byte b:encrypt2BytesOnLog("1")){
//			System.out.print(b+" ");
//		}
//		System.out.println("\r\n"+getString(encrypt2BytesByMD5(getBytes("z"))));

//		GenerateEncryCode("jxslyz19900502","+ÝÍE|ô<rÇ»");
//		GenerateEncryCode("lyz","7-µx95");
//		GenerateEncryCode("xxs2013","ÅÁõ.®~8");
//		GenerateEncryCode("aaa","»XI1>§");
		System.out.println(byte2strHex(encrypt2BytesByMD5(getBytes("123444")),0));
		System.out.println(encrypt2HexStringByMD5(""));
		System.out.println(encode2StringByBase64("111"));
		//System.out.println(encrypt2String(true,"MD5",1));
	}
	 //************************TestMain**************************************
	
//	public static Object encrypt2String(boolean isEncrypt,String encryptType,String returnType,Object inputObj){
//		if(StringUtils.isNullOrEmpty(encryptType)||inputObj==null){
//			return null;
//		}	
//		byte[] bytes=null;
//		String string=null;
//		if(inputObj instanceof byte[]){
//			 bytes=(byte[]) inputObj;
//		}else if(inputObj instanceof Integer){
//			string=Integer.toString((Integer)inputObj) ;
//		}else if(inputObj instanceof String){
//			string=(String)inputObj;
//		}else{	
//			return null;
//		}
//		
//		if(bytes!=null){
//			if(isEncrypt){
//				// MD5
//				if("0".equals(encryptType)){
//					bytes=encrypt2BytesByMD5(bytes);
//					// String Type
//					if("0".equals(returnType)){
//						return byte2strHex(bytes);
//					}else if("1".equals(returnType)){// byte[] Type
//						return StringUtils.getBytes(byte2strHex(bytes));
//					}else{
//						
//					}
//				}else if("1".equals(encryptType)){// DES
//					bytes=encrypt2BytesByDES(bytes);
//				}
//			}else{
//				
//			}
//		}else{
//			
//		}
//		return encryptType;
//	}
	
	
	private static void GenerateEncryCode(String primtiveString,String encryptedString){
		System.out.println(encrypt2StringByDES(primtiveString));
		System.out.println(decrypt2StringByDES(encryptedString)+"\r\n");
	}
	
	/**
	 * 
	 * @Title: encrypt2HexStringByMD5
	 * @Description: TODO
	 * @param @param encryptString
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2HexStringByMD5(String encryptString){
		return byte2strHex(encrypt2BytesByMD5(getBytes(encryptString)),0);
	}
	
	/**
	 * 
	 * @Title: Encrypt2BytesByMD5
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesByMD5(byte[] encryptBytes) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		//return  encode2BytesByBase64(md5.digest(encryptBytes));
		return  md5.digest(encryptBytes);
	}
	
	
	/**
	 * 
	 * @Title: encrypt2BytesLogon
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesOnLog(byte[] encryptBytes,String charsetName) {
		return  encrypt2BytesByDES(encrypt2BytesByMD5(encryptBytes),charsetName);
	}
	
	
	/**
	 * 
	 * @Title: Encrypt2BytesByMD5
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesOnLog(String encryptStr,String charsetName) {
		return encrypt2BytesOnLog(getBytes(encryptStr,charsetName),charsetName);
	}
	
	
	/**
	 * 
	 * @Title: Encrypt2BytesByMD5
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesOnLog(String encryptStr) {
		return encrypt2BytesOnLog(encryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: Encrypt2StringByMD5
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param charsetName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringOnLog(String encryptStr,String charsetName) {
		return getString(encrypt2BytesOnLog(encryptStr,charsetName));
	}
	
	/**
	 * 
	 * @Title: Encrypt2StringByMD5
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringOnLog(String encryptStr) {
		return encrypt2StringOnLog(encryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: Encry2BytesByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesByDES(byte[] encryptBytes,String charsetName){
		byte[]  encryptedBytes=null;
		try {
			String MD5Key = new String(Coder.encryptMD5(getBytes(key,charsetName)));
			String initkey = DESCoder.initKey(MD5Key);
		    encryptedBytes= DESCoder.encrypt(encryptBytes, initkey);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return encryptedBytes;
	}
	
	/**
	 * 
	 * @Title: decrypt2BytesByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] decrypt2BytesByDES(byte[] decryptBytes,String charsetName){
		byte[]  encryptedBytes=null;
		try {
			String MD5Key = new String(Coder.encryptMD5(getBytes(key,charsetName)));
			String initkey = DESCoder.initKey(MD5Key);
		    encryptedBytes= DESCoder.decrypt(decryptBytes, initkey);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return encryptedBytes;	
	}
	
	
	/**
	 * 
	 * @Title: Encrypt2BytesByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesByDES(byte[] encryptBytes){
		return encrypt2BytesByDES(encryptBytes,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: decrypt2BytesByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] decrypt2BytesByDES(byte[] decryptBytes){
		return decrypt2BytesByDES(decryptBytes,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesByDES(String encryptStr,String charsetName){
		return encrypt2BytesByDES(getBytes(encryptStr,charsetName),charsetName);
	}
	
	
	/**
	 * 
	 * @Title: decrypt2BytesByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] decrypt2BytesByDES(String decryptStr,String charsetName){
		return decrypt2BytesByDES(getBytes(decryptStr,charsetName),charsetName);
	}
	
	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] encrypt2BytesByDES(String encryptStr){
		return encrypt2BytesByDES(encryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: decrypt2BytesByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static final byte[] decrypt2BytesByDES(String decryptStr){
		return decrypt2BytesByDES(decryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}

	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringByDES(byte[] encryptBytes,String charsetName){
		return getString(encrypt2BytesByDES(encryptBytes,charsetName));
	}
	
	
	/**
	 * 
	 * @Title: decrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String decrypt2StringByDES(byte[] decryptBytes,String charsetName){
		return getString(decrypt2BytesByDES(decryptBytes,charsetName));
	}
	
	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringByDES(byte[] encryptBytes){
		return encrypt2StringByDES(encryptBytes,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: decrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptBytes
	 * @param @param key
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String decrypt2StringByDES(byte[] decryptBytes){
		return decrypt2StringByDES(decryptBytes,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringByDES(String encryptStr,String charsetName){
		return getString(encrypt2BytesByDES(encryptStr,charsetName));
	}
	
	
	/**
	 * 
	 * @Title: decrypt2StringByDES
	 * @Description: TODO
	 * @param @param decryptStr
	 * @param @param key
	 * @param @param charsetName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String decrypt2StringByDES(String decryptStr,String charsetName){
		return getString(decrypt2BytesByDES(decryptStr,charsetName));
	}
	
	
	/**
	 * 
	 * @Title: encrypt2StringByDES
	 * @Description: TODO
	 * @param @param encryptStr
	 * @param @param key
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String encrypt2StringByDES(String encryptStr){
		return encrypt2StringByDES(encryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: decrypt2StringByDES
	 * @Description: TODO
	 * @param @param decryptStr
	 * @param @param key
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static final String decrypt2StringByDES(String decryptStr){
		return decrypt2StringByDES(decryptStr,EConstants.ENCODING_NAME_ISO_8859_1);
	}
	
	
	/**
	 * 
	 * @Title: encode2StringByBase64
	 * @Description: TODO
	 * @param @param bytes
	 * @param @return
	 * @return String
	 * @throws
	 */
	@SuppressWarnings("static-access")
	public static String encode2StringByBase64(byte[] bytes){
		Base64 base64en = new Base64();
		return base64en.encodeBase64String(bytes);
	}
	
	
	/**
	 * 
	 * @Title: encode2StringByBase64
	 * @Description: TODO
	 * @param @param encodeStr
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static String encode2StringByBase64(String encodeStr){
		return encode2StringByBase64(getBytes(encodeStr));
	}
	
	
	/**
	 * 
	 * @Title: encode2BytesByBase64
	 * @Description: TODO
	 * @param @param bytes
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static byte[] encode2BytesByBase64(byte[] bytes){
		return getBytes(encode2StringByBase64(bytes));
	}
	
	
	/**
	 * 
	 * @Title: encode2BytesByBase64
	 * @Description: TODO
	 * @param @param encodeStr
	 * @param @return
	 * @return byte[]
	 * @throws
	 */
	public static byte[] encode2BytesByBase64(String encodeStr){
		return getBytes(encode2StringByBase64(encodeStr));
	}
	
	
	/**
	 * 
	 * @Title: byte2str
	 * @Description: COnvert to HEX
	 * @param @param bytes
	 * @param @return
	 * @return String
	 * @throws
	 */
	@SuppressWarnings("unused")
	public static String byte2strHex(byte[] bytes,int caseType) {
		int len = bytes.length;
		StringBuffer result = new StringBuffer();
		char[] hex;
		if(caseType==0){
			hex=hexLowCase;
		}else{
			hex=hexUpCase;
		}
		for (int i = 0; i < len; i++) {
			byte byte0 = bytes[i];
			result.append(hex[byte0 >>> 4 & 0xf]);
			result.append(hex[byte0 & 0xf]);
		}
		return result.toString();
	}
}
